#include "bsp_flash.h"
#include "mcc_generated_files/mcc.h"
#include "mian.h"

/* ??Flsh???GPIO??  */
#define SF_CS_0()			IO_RC5_SetLow()
#define SF_CS_1()			IO_RC5_SetHigh()

#define CMD_AAI       0xAD  	/* AAI ??????(FOR SST25VF016B) */
#define CMD_DISWR	  0x04		/* ???, ??AAI?? */
#define CMD_EWRSR	  0x50		/* ??????????? */
#define CMD_WRSR      0x01  	/* ???????? */
#define CMD_WREN      0x06		/* ????? */
#define CMD_READ      0x03  	/* ?????? */
#define CMD_RDSR      0x05		/* ???????? */
#define CMD_RDID      0x9F		/* ???ID?? */
#define CMD_SE        0x20		/* ?????? */
#define CMD_BE        0xC7		/* ?????? */
#define DUMMY_BYTE    0xA5		/* ???????????????? */

#define WIP_FLAG      0x01		/* ??????????????WIP) */

SFLASH_T g_tSF;

static void sf_WriteEnable(void);
static void sf_WriteStatus(uint8_t _ucValue);
static void sf_WaitForWriteEnd(void);
static uint8_t sf_NeedErase(uint8_t * _ucpOldBuf, uint8_t *_ucpNewBuf, uint16_t _uiLen);
static uint8_t sf_CmpData(uint32_t _uiSrcAddr, uint8_t *_ucpTar, uint32_t _uiSize);
static uint8_t sf_AutoWritePage(uint8_t *_ucpSrc, uint32_t _uiWrAddr, uint16_t _usWrLen);
//static uint8_t s_spiBuf[4*1024];	/* ???????????page???????????page?? */

void sf_CfgSpiHard(void);
static void sf_ConfigGPIO(void);
static void sf_SetCS(uint8_t _level);


/*
*********************************************************************************************************
*	? ? ?: sf_ConfigGPIO
*	????: ????Flash???GPIO? ???????
*	?    ?: ?
*	? ? ?: ?
*********************************************************************************************************
*/
static void sf_ConfigGPIO(void)
{
	/*
		???STM32-V4 ????????  ??Flash??? W25Q64BVSSIG (80MHz)
		PF8/SF_CS
	*/
//	GPIO_InitTypeDef GPIO_InitStructure;
//
//	/* ??GPIO ?? */
//	RCC_APB2PeriphClockCmd(SF_RCC_CS, ENABLE);
//
//	/* ????????????? */
//	sf_SetCS(1);		/* ???????? */
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	GPIO_InitStructure.GPIO_Pin = SF_PIN_CS;
//	GPIO_Init(SF_PORT_CS, &GPIO_InitStructure);
}
/*
*********************************************************************************************************
*	? ? ?: sf_CfgSpiHard
*	????: ??STM32??SPI??????????????????SPI?????Flash?
*	?    ?: ?
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_CfgSpiHard(void)
{
//	SPI_InitTypeDef  SPI_InitStructure;
//
//	/* ??SPI???? */
//	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	/* ?????2???? */
//	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		/* STM32?SPI???? ????? */
//	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	/* ????? ? 8? */
//	/* SPI_CPOL?SPI_CPHA????????????????????
//	   ????: ????????,?2???????????)
//	*/
//	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;			/* ????????? */
//	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;		/* ????2??????? */
//	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;			/* ??????????? */
//
//	/* ?????????? SPI_BaudRatePrescaler_8 ???SCK?? 96ns, 10.4MHz */
//	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
//
//	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	/* ???????????? */
//	SPI_InitStructure.SPI_CRCPolynomial = 7;			/* CRC???????????7?????? */
//	SPI_Init(SPI1, &SPI_InitStructure);
//
//	SPI_Cmd(SPI1, ENABLE);				/* ??SPI  */
}
/*
*********************************************************************************************************
*	? ? ?: sf_SetCS(0)
*	????: ??CS? ?????SPI???
*	?    ?: ?
	? ? ?: ?
*********************************************************************************************************
*/
static void sf_SetCS(uint8_t _level)
{
	if (_level == 0)
	{
        SF_CS_0();
//		bsp_SpiBusEnter();	/* ??SPI??? ?????? */
//
//		#ifdef SOFT_SPI		/* ??SPI */
//			bsp_SetSpiSck(1);
//			SF_CS_0();
//		#endif
//
//		#ifdef HARD_SPI		/* ??SPI */
//
//			bsp_SPI_Init(SPI_Direction_2Lines_FullDuplex | SPI_Mode_Master | SPI_DataSize_8b
//				| SPI_CPOL_High | SPI_CPHA_2Edge | SPI_NSS_Soft | SPI_BaudRatePrescaler_8 | SPI_FirstBit_MSB);
//
//			SF_CS_0();
//		#endif
	}
	else
	{
		SF_CS_1();

		//bsp_SpiBusExit();	/* ??SPI??? ?????? */
	}
}
static void bsp_spiWrite1(unsigned char byte)
{
    SPI2_Exchange8bit(byte);
}
static unsigned char bsp_spiRead1(void)
{
    return SPI2_Exchange8bit(SPI2_DUMMY_DATA);
}
/*
*********************************************************************************************************
*	? ? ?: sf_WaitForWriteEnd
*	????: ????????????????????
*	?    ?:  ?
*	? ? ?: ?
*********************************************************************************************************
*/
static void sf_WaitForWriteEnd(void)
{
	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_RDSR);							/* ????? ?????? */
	while((bsp_spiRead1() & WIP_FLAG) == 0x01);	/* ???????????? */
	sf_SetCS(1);									/* ???? */
}
/*
*********************************************************************************************************
*	? ? ?: sf_WriteStatus
*	????: ??????
*	?    ?:  _ucValue : ???????
*	? ? ?: ?
*********************************************************************************************************
*/
static void sf_WriteStatus(uint8_t _ucValue)
{

	if (g_tSF.ChipID == SST25VF016B_ID)
	{
		/* ?1??????????? */
		sf_SetCS(0);									/* ???? */
		bsp_spiWrite1(CMD_EWRSR);							/* ????? ???????? */
		sf_SetCS(1);									/* ???? */

		/* ?2????????? */
		sf_SetCS(0);									/* ???? */
		bsp_spiWrite1(CMD_WRSR);							/* ????? ?????? */
		bsp_spiWrite1(_ucValue);							/* ???????????? */
		sf_SetCS(1);									/* ???? */
	}
	else
	{
		sf_SetCS(0);									/* ???? */
		bsp_spiWrite1(CMD_WRSR);							/* ????? ?????? */
		bsp_spiWrite1(_ucValue);							/* ???????????? */
		sf_SetCS(1);									/* ???? */
	}
}
/*
*********************************************************************************************************
*	? ? ?: sf_WriteEnable
*	????: ??????????
*	?    ?:  ?
*	? ? ?: ?
*********************************************************************************************************
*/
static void sf_WriteEnable(void)
{
	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_WREN);								/* ???? */
	sf_SetCS(1);									/* ???? */
}
/***************************** ????? www.armfly.com (END OF FILE) *********************************/

/*
*********************************************************************************************************
*	? ? ?: bsp_InitSpiFlash
*	????: ?????Flash???????STM32?SPI???GPIO)
*	?    ?:  ?
*	? ? ?: ?
*********************************************************************************************************
*/
void bsp_InitSFlash(void)
{
	sf_ConfigGPIO();			/* ??GPIO */
	
	//sf_CfgSpiHard();

	sf_ReadInfo();				/* ???????? */
    sf_ReadInfo();				/* ???????? */
    sf_ReadInfo();				/* ???????? */

	sf_SetCS(0);				/* ?????????Flash?? */
	bsp_spiWrite1(CMD_DISWR);		/* ?????????,???????? */
	sf_SetCS(1);				/* ?????????Flash?? */

	sf_WaitForWriteEnd();		/* ????Flash?????? */

	sf_WriteStatus(0);			/* ????BLOCK???? */
}
/*
*********************************************************************************************************
*	? ? ?: sf_ReadID
*	????: ????ID
*	?    ?:  ?
*	? ? ?: 32bit???ID (??8bit?0???ID???24bit?
*********************************************************************************************************
*/
uint32_t sf_ReadID(void)
{
	uint32_t uiID;
	uint8_t id1, id2, id3;

	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_RDID);								/* ???ID?? */
	id1 = bsp_spiRead1();					/* ?ID??1??? */
	id2 = bsp_spiRead1();					/* ?ID??2??? */
	id3 = bsp_spiRead1();					/* ?ID??3??? */
	sf_SetCS(1);									/* ???? */

	uiID = ((uint32_t)id1 << 16) | ((uint32_t)id2 << 8) | id3;

	return uiID;
}
/*
*********************************************************************************************************
*	? ? ?: sf_ReadInfo
*	????: ????ID,???????
*	?    ?:  ?
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_ReadInfo(void)
{
	/* ??????Flash?? */
	{
		g_tSF.ChipID = sf_ReadID();	/* ??ID */

		switch (g_tSF.ChipID)
		{
			case SST25VF016B_ID:
				//strcpy(g_tSF.ChipName, "SST25VF016B");
				g_tSF.TotalSize = 2 * 1024 * 1024;	/* ??? = 2M */
				g_tSF.PageSize = 4 * 1024;			/* ???? = 4K */
				break;

			case MX25L1606E_ID:
				//strcpy(g_tSF.ChipName, "MX25L1606E");
				g_tSF.TotalSize = 2 * 1024 * 1024;	/* ??? = 2M */
				g_tSF.PageSize = 4 * 1024;			/* ???? = 4K */
				break;

			case W25Q64_ID:
				//strcpy(g_tSF.ChipName, "W25Q64");
				g_tSF.TotalSize = 8 * 1024 * 1024;	/* ??? = 8M */
				g_tSF.PageSize = 4 * 1024;			/* ???? = 4K */
				break;


			case W25Q128_ID:
				//strcpy(g_tSF.ChipName, "W25Q128");
				g_tSF.TotalSize = 16 * 1024 * 1024;	/* ??? = 16M */
				g_tSF.PageSize = 4 * 1024;			/* ???? = 4K */
				break;			
            case FM25Q04:
                g_tSF.TotalSize = 524288;	/* ??? = 16M */
				g_tSF.PageSize = 4 * 1024;			/* ???? = 4K */
                break;
			default:
				//strcpy(g_tSF.ChipName, "Unknow Flash");
				g_tSF.TotalSize = 2 * 1024 * 1024;
				g_tSF.PageSize = 4 * 1024;
				break;
		}
	}
}

/*
*********************************************************************************************************
*	? ? ?: sf_EraseSector
*	????: ???????
*	?    ?:  _uiSectorAddr : ????
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_EraseSector(uint32_t _uiSectorAddr)
{
	sf_WriteEnable();								/* ??????? */

	/* ?????? */
	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_SE);								/* ?????? */
	bsp_spiWrite1((_uiSectorAddr & 0xFF0000) >> 16);	/* ????????8bit */
	bsp_spiWrite1((_uiSectorAddr & 0xFF00) >> 8);		/* ????????8bit */
	bsp_spiWrite1(_uiSectorAddr & 0xFF);				/* ???????8bit */
	sf_SetCS(1);									/* ???? */

	sf_WaitForWriteEnd();							/* ????Flash??????? */
}

/*
*********************************************************************************************************
*	? ? ?: sf_EraseChip
*	????: ??????
*	?    ?:  ?
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_EraseChip(void)
{
	sf_WriteEnable();								/* ??????? */

	/* ?????? */
	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_BE);							/* ???????? */
	sf_SetCS(1);									/* ???? */

	sf_WaitForWriteEnd();							/* ????Flash??????? */
}
/*
*********************************************************************************************************
*	? ? ?: sf_ReadBuffer
*	????: ??????????????????????
*	?    ?:  	_pBuf : ???????
*				_uiReadAddr ????
*				_usSize ?????, ????PAGE_SIZE,???????????
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_ReadBuffer(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize)
{
	/* ??????????0??????Flash?????????? */
	if ((_uiSize == 0) ||(_uiReadAddr + _uiSize) > g_tSF.TotalSize)
	{
		return;
	}

	/* ?????? */
	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_READ);							/* ????? */
	bsp_spiWrite1((_uiReadAddr & 0xFF0000) >> 16);	/* ????????8bit */
	bsp_spiWrite1((_uiReadAddr & 0xFF00) >> 8);		/* ????????8bit */
	bsp_spiWrite1(_uiReadAddr & 0xFF);				/* ???????8bit */
	while (_uiSize--)
	{
		*_pBuf++ = bsp_spiRead1();			/* ?????????pBuf????????1 */
	}
	sf_SetCS(1);									/* ???? */
}

/*
*********************************************************************************************************
*	? ? ?: sf_CmpData
*	????: ??Flash???.
*	?    ?:  	_ucpTar : ?????
*				_uiSrcAddr ?Flash??
*				_uiSize ?????, ????PAGE_SIZE,???????????
*	? ? ?: 0 = ??, 1 = ??
*********************************************************************************************************
*/
static uint8_t sf_CmpData(uint32_t _uiSrcAddr, uint8_t *_ucpTar, uint32_t _uiSize)
{
	uint8_t ucValue;

	/* ??????????0??????Flash?????????? */
	if ((_uiSrcAddr + _uiSize) > g_tSF.TotalSize)
	{
		return 1;
	}

	if (_uiSize == 0)
	{
		return 0;
	}

	sf_SetCS(0);									/* ???? */
	bsp_spiWrite1(CMD_READ);							/* ????? */
	bsp_spiWrite1((_uiSrcAddr & 0xFF0000) >> 16);		/* ????????8bit */
	bsp_spiWrite1((_uiSrcAddr & 0xFF00) >> 8);		/* ????????8bit */
	bsp_spiWrite1(_uiSrcAddr & 0xFF);					/* ???????8bit */
	while (_uiSize--)
	{
		/* ????? */
		ucValue = bsp_spiRead1();
		if (*_ucpTar++ != ucValue)
		{
			sf_SetCS(1);
			return 1;
		}
	}
	sf_SetCS(1);
	return 0;
}

/*
*********************************************************************************************************
*	? ? ?: sf_NeedErase
*	????: ???PAGE?????????
*	?    ?:   _ucpOldBuf ? ???
*			   _ucpNewBuf ? ???
*			   _uiLen ??????????????
*	? ? ?: 0 : ?????? 1 ?????
*********************************************************************************************************
*/
static uint8_t sf_NeedErase(uint8_t * _ucpOldBuf, uint8_t *_ucpNewBuf, uint16_t _usLen)
{
	uint16_t i;
	uint8_t ucOld;

	/*
	???1??old ??, new ??
	      old    new
		  1101   0101
	~     1111
		= 0010   0101

	???2?: old ?????? new ??
		  0010   old
	&	  0101   new
		 =0000

	???3?: ???0,???????. ????????
	*/

	for (i = 0; i < _usLen; i++)
	{
		ucOld = *_ucpOldBuf++;
		ucOld = ~ucOld;

		/* ???????: if (ucOld & (*_ucpNewBuf++) != 0) */
		if ((ucOld & (*_ucpNewBuf++)) != 0)
		{
			return 1;
		}
	}
	return 0;
}
/*
*********************************************************************************************************
*	? ? ?: sf_PageWrite
*	????: ???page?????????????????????4K)
*	?    ?:  	_pBuf : ???????
*				_uiWriteAddr ????????
*				_usSize ??????????????
*	? ? ?: ?
*********************************************************************************************************
*/
void sf_PageWrite(uint8_t * _pBuf, uint32_t _uiWriteAddr, uint16_t _usSize)
{
	uint32_t i, j;

	if (g_tSF.ChipID == SST25VF016B_ID)
	{
		/* AAI?????????????? */
		if ((_usSize < 2) && (_usSize % 2))
		{
			return ;
		}

		sf_WriteEnable();								/* ??????? */

		sf_SetCS(0);									/* ???? */
		bsp_spiWrite1(CMD_AAI);							/* ??AAI??(????????) */
		bsp_spiWrite1((_uiWriteAddr & 0xFF0000) >> 16);	/* ????????8bit */
		bsp_spiWrite1((_uiWriteAddr & 0xFF00) >> 8);		/* ????????8bit */
		bsp_spiWrite1(_uiWriteAddr & 0xFF);				/* ???????8bit */
		bsp_spiWrite1(*_pBuf++);							/* ???1??? */
		bsp_spiWrite1(*_pBuf++);							/* ???2??? */
		sf_SetCS(1);									/* ???? */

		sf_WaitForWriteEnd();							/* ????Flash??????? */

		_usSize -= 2;									/* ??????? */

		for (i = 0; i < _usSize / 2; i++)
		{
			sf_SetCS(0);								/* ???? */
			bsp_spiWrite1(CMD_AAI);						/* ??AAI??(????????) */
			bsp_spiWrite1(*_pBuf++);						/* ???? */
			bsp_spiWrite1(*_pBuf++);						/* ???? */
			sf_SetCS(1);								/* ???? */
			sf_WaitForWriteEnd();						/* ????Flash??????? */
		}

		/* ??????? */
		sf_SetCS(0);
		bsp_spiWrite1(CMD_DISWR);
		sf_SetCS(1);

		sf_WaitForWriteEnd();							/* ????Flash??????? */
	}
	else	/* for MX25L1606E ? W25Q64BV */
	{
		for (j = 0; j < _usSize / 256; j++)
		{
			sf_WriteEnable();								/* ??????? */

			sf_SetCS(0);									/* ???? */
			bsp_spiWrite1(0x02);								/* ??AAI??(????????) */
			bsp_spiWrite1((_uiWriteAddr & 0xFF0000) >> 16);	/* ????????8bit */
			bsp_spiWrite1((_uiWriteAddr & 0xFF00) >> 8);		/* ????????8bit */
			bsp_spiWrite1(_uiWriteAddr & 0xFF);				/* ???????8bit */

			for (i = 0; i < 256; i++)
			{
				bsp_spiWrite1(*_pBuf++);					/* ???? */
			}

			sf_SetCS(1);								/* ???? */

			sf_WaitForWriteEnd();						/* ????Flash??????? */

			_uiWriteAddr += 256;
		}

		/* ??????? */
		sf_SetCS(0);
		bsp_spiWrite1(CMD_DISWR);
		sf_SetCS(1);

		sf_WaitForWriteEnd();							/* ????Flash??????? */
	}
}